package com.tianhua.javs.core.engine.handler;

import com.tianhua.javs.client.bean.JavsTranslateContextBean;
import com.tianhua.javs.client.bean.ScriptVarMappingBean;
import com.tianhua.javs.client.bean.TranslateResultBean;
import com.tianhua.javs.client.enums.BusinessKeyWardEnum;
import com.tianhua.javs.client.enums.SegmentSceneEnum;
import com.tianhua.javs.client.model.AbstractClassModel;
import com.tianhua.javs.client.model.FieldModel;
import com.tianhua.javs.client.model.MethodModel;
import com.tianhua.javs.core.constant.TagConstants;
import com.tianhua.javs.core.parse.JavsContentParseService;
import com.tianhua.javs.core.parse.SegmentSpreadParseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * Description:抽象元素场景处理服务
 * date: 2022/2/24
 *
 * @author shenshuai
 * @version 1.0.0
 * @since JDK 1.8
 */
@Component(value = "AbstractElementHandler")
public abstract class AbstractElementHandler {

    @Autowired
    private JavsContentParseService javsContentParseService;

    @Autowired
    private SegmentSpreadParseService segmentSpreadParseService;

    /**
     * 抽象翻译处理服务，返回是否已匹配处理的结果bean
     * 由pipeline根据处理结果动态翻译
     * @param javsShell
     * @param keyWard
     * @param translateContextBean
     * @return
     */
    abstract TranslateResultBean handleTranslate(String javsShell, String keyWard, JavsTranslateContextBean translateContextBean, SegmentSceneEnum sceneEnum);

    /**
     * 从代码段关键字中解析javs变量
     * @param keyWard
     * @return
     */
    public String getVarCodeFromKeyWard(String keyWard){
        String [] referArr = keyWard.split("\\.");
        return referArr[0];
    }

    public String getNewKeWard(String keyWard){
        int index = keyWard.indexOf("(");
        String newKeyWard = keyWard;
        if(index > 0) {
            newKeyWard = keyWard.substring(0, index);
        }
        return newKeyWard;
    }


    /**
     * 增加运行时变量
     * @param javsShell
     * @param varClassName
     * @param translateContextBean
     */
    public void addRuntimeVarAssign(String javsShell, String varClassName, JavsTranslateContextBean translateContextBean, boolean asField){
        String varName = javsShell.split(TagConstants.EQ)[0].trim();
        ScriptVarMappingBean scriptVarMappingBean = ScriptVarMappingBean.builder()
                .varClassName(varClassName)
                .javsVarCode(varName).build();
        addRunTimeVar(scriptVarMappingBean, translateContextBean, varName);
        addRunTimePackage(translateContextBean, varClassName);
        if(asField){
            addRunTimeField(translateContextBean, varClassName, varName,true);
        }

    }

    public MethodModel searchMethod(String keyWard, JavsTranslateContextBean translateContextBean){
        String [] referArr = keyWard.split("\\.");
        String classVarName = referArr[0];
        String methodName = referArr[1].split("\\(")[0];
        List<String> paramList = javsContentParseService.getParamList(referArr[1]);

        return translateContextBean.getDomainModelBean().searchMethod(classVarName,methodName,paramList.size());
    }

    /**
     * 构建整个赋值语句
     * @param javsShell
     * @param varClassType
     * @param varName
     * @param businessSegment
     * @return
     */
    public String buildAssignSegment(String javsShell, String varClassType, String varName,String businessSegment){
        StringBuilder builder = new StringBuilder(segmentSpreadParseService.getBlankPrefix(javsShell));
        builder.append(varClassType.trim());
        builder.append(TagConstants.BLANK_ONE);
        if(javsShell.contains(TagConstants.EQ)){
            String varCode = javsShell.split(TagConstants.EQ)[0].trim();
            if(BusinessKeyWardEnum.isJavsModel(varCode)){
                varCode = varClassType.substring(0,1).toLowerCase() + varClassType.substring(1);
                builder.append(varCode);
            }else {
                builder.append(varCode);
            }
        }else {
            builder.append(varName);
        }
        builder.append(TagConstants.BLANK_ONE);
        builder.append(TagConstants.EQ);
        builder.append(TagConstants.BLANK_ONE);
        builder.append(businessSegment.trim());
        builder.append(TagConstants.ROW_END);
        return builder.toString();
    }


    /**
     * 增加运行时变量
     * @param scriptVarMappingBean
     * @param translateContextBean
     * @param varName
     */
    public  void addRunTimeVar(ScriptVarMappingBean scriptVarMappingBean, JavsTranslateContextBean translateContextBean, String varName){
        scriptVarMappingBean.setJavsVarCode(varName);
        AbstractClassModel abstractClassModel = translateContextBean.getDomainModelBean().searchClass(null, scriptVarMappingBean.getVarClassName());
        scriptVarMappingBean.setReferClassModel(abstractClassModel);
        translateContextBean.getCurrentScriptMethodBean().addPackage(abstractClassModel.getPackageName());
        translateContextBean.getCurrentScriptMethodBean().addRunTimeVar(scriptVarMappingBean);
    }


    /**
     * 增加运行时需要的类包
     * 增加
     * @param translateContextBean
     * @param className
     * @param beanField
     */
    public void addRunTimeField(JavsTranslateContextBean translateContextBean, String className, String varName, boolean beanField){
        AbstractClassModel abstractClassModel = translateContextBean.getDomainModelBean().searchClass(null, className);
        translateContextBean.getCurrentScriptMethodBean().addPackage(abstractClassModel.getPackageName());
        if(beanField){
            //这里根据代码元素或者类的多接口实现等进行动态注入
            FieldModel  fieldModel = new FieldModel();
            fieldModel.setFieldName(className + TagConstants.BLANK_ONE + varName);
            fieldModel.setVisibility(TagConstants.PRIVATE);
            fieldModel.setAnnotation(TagConstants.AUTOWIRED);
            fieldModel.setFieldType(className);
            translateContextBean.getCurrentScriptMethodBean().addFieldModel(fieldModel);
        }
    }

    /**
     * 增加运行时导入包
     * @param translateContextBean
     * @param className
     */
    public void addRunTimePackage(JavsTranslateContextBean translateContextBean, String className ){
        AbstractClassModel abstractClassModel = translateContextBean.getDomainModelBean().searchClass(null, className);
        if(abstractClassModel != null){
            translateContextBean.getCurrentScriptMethodBean().addPackage(abstractClassModel.getPackageName());
        }
    }


}
